package net.stevechaloner.idea.ffs.actions;

import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import net.stevechaloner.idea.ffs.FirefoxSearchBundle;
import net.stevechaloner.idea.ffs.config.ConfigComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.JComponent;
import javax.swing.JOptionPane;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

/**
 * @author Steve Chaloner
 */
abstract class AbstractSearchAction extends AnAction implements SearchAction
{
    /**
     *
     */
    private final Project project;

    /**
     *
     * @param project
     */
    protected AbstractSearchAction(@NotNull Project project)
    {
        this.project = project;
    }

    // javadoc unnecessary
    public void setName(String name)
    {
        this.getTemplatePresentation().setText(name);
    }

    // javadoc unnecessary
    public String getName()
    {
        return this.getTemplatePresentation().getText();
    }

    /**
     * Open the given URL in the standard browser.
     *
     * @param url the URL to open
     */
    protected void openUrl(String url)
    {
        BrowserUtil.launchBrowser(url);
    }

    /**
     * Gets the current selection or word under the caret in the given editor.
     *
     * @param editor the current editor
     * @param encoding the string encoding
     * @return the current selection or word under the caret
     */
    @Nullable
    protected String getInputFromEditor(@NotNull Editor editor,
                                        @NotNull String encoding)
    {
        SelectionModel selectionModel = editor.getSelectionModel();
        String input;
        if (selectionModel.hasSelection())
        {
            input = selectionModel.getSelectedText();

            if (!StringUtil.isEmptyOrSpaces(input))
            {
                ConfigComponent configComponent = project.getComponent(ConfigComponent.class);
                List<String> list = configComponent.getConfig().getQuotedSearchProviders();
                if (list.contains(getName()) && !input.startsWith("\"") && !input.endsWith("\""))
                {
                    input = '"' + input.trim() + '"';
                }
            }
        }
        else
        {
            int offset = editor.getCaretModel().getOffset();
            CharSequence editorText = editor.getDocument().getCharsSequence();
            input = getWordAtCursor(editorText,
                                    offset);
        }
        String word = null;
        try
        {
            if (!StringUtil.isEmptyOrSpaces(input))
            {
                word = URLEncoder.encode(input,
                                         encoding);
            }
        }
        catch (UnsupportedEncodingException e1)
        {
            e1.printStackTrace();
        }

        return word;
    }

    /**
     * Gets the word under the caret.
     * <p>
     * Adapted from the GoogleSearch example plugin.
     * <p>
     * @param editorText
     * @param cursorOffset
     * @return the word under the caret, or null
     */
    @Nullable
    private String getWordAtCursor(CharSequence editorText,
                                   int cursorOffset)
    {
        String word = null;
        if (editorText.length() != 0)
        {
            if (cursorOffset > 0 && !Character.isJavaIdentifierPart(editorText.charAt(cursorOffset)) && Character.isJavaIdentifierPart(editorText.charAt(cursorOffset - 1)))
            {
                cursorOffset--;
            }
            if (Character.isJavaIdentifierPart(editorText.charAt(cursorOffset)))
            {
                int start = cursorOffset;
                int end = cursorOffset;
                for (; start > 0 && Character.isJavaIdentifierPart(editorText.charAt(start - 1)); start--)
                {
                }
                for (; end < editorText.length() && Character.isJavaIdentifierPart(editorText.charAt(end)); end++)
                {
                }
                word = editorText.subSequence(start, end).toString();
            }
        }

        return word;
    }

    protected void showInvalidInput(JComponent component)
    {
        JOptionPane.showMessageDialog(component,
                                      FirefoxSearchBundle.message("warning.nothing.selected"));
    }
}
